package cn.suimg.wechat.timer;

import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;

/**
 * 自动删除文件定时任务
 * @author Suimg
 */
@Configuration
public class FileAutoDeleteTimer {

    /**
     * 需要删除的文件列表
     */
    private static final List<TimerDeleteFile> NEED_DELETE_FILES = new ArrayList<>();

    /**
     * 删除文件触发条件:当前时间超过了处决时间
     */
    private static final Predicate<TimerDeleteFile> CAN_EXECUTE = timerDeleteFile -> System.currentTimeMillis() > timerDeleteFile.getExecuteDate().getTime();

    /**
     * Logger
     */
    private static final Logger logger = LoggerFactory.getLogger(FileAutoDeleteTimer.class);

    /**
     * 提交一个文件到需要删除的队列
     * @param file
     */
    public static void commitFile(File file){
        if(file == null)
            return;
        NEED_DELETE_FILES.add(new TimerDeleteFile(){{
            setExecuteFile(file);
            //设置20分钟之后删除,避免文件还没下载完就被删除
            setExecuteDate(new Date(System.currentTimeMillis() + 1200000L));
        }});
    }

    /**
     * 每10分钟清空一次列表
     */
    @Scheduled(fixedDelay = 600000)
    public void accept(){
        NEED_DELETE_FILES.stream().filter(Objects::nonNull).filter(CAN_EXECUTE).map(TimerDeleteFile::getExecuteFile).forEach(file -> {
            try{
                logger.info("timer auto delete file {} => {}",file.getAbsolutePath(),file.delete() ? "success" : "failed");
                NEED_DELETE_FILES.stream().filter(timerDeleteFile -> timerDeleteFile.getExecuteFile() == file).forEach(NEED_DELETE_FILES::remove);
            }catch (SecurityException e){
                logger.error("delete file failed",e);
            }
        });
    }

    @Data
    private static class TimerDeleteFile {

        /**
         * 要处决的文件
         */
        private File executeFile;

        /**
         * 要处决的日期
         */
        private Date executeDate;

    }
}
